package org.kugua.strategy.impl;

import lombok.Getter;
import lombok.Setter;
import org.kugua.context.CaptchaContext;
import org.kugua.dto.Captcha;
import org.kugua.enums.CaptchaEnum;
import org.kugua.enums.FontEnum;
import org.kugua.library.Library;
import org.kugua.library.impl.PhraseLibrary;
import org.kugua.strategy.ParentCaptchaStrategy;
import org.kugua.utils.RandomUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 点触类-验证码
 *
 * @author 苦瓜
 * @create 2024-08-26
 * @since 1.0.0
 */
@Setter
@Getter
public class ClickTouchCaptchaStrategy extends ParentCaptchaStrategy {

    private Library<String> phraseLibrary = new PhraseLibrary();

    /**
     * 验证码内容填充
     *
     * @param context 内容
     * @return Captcha
     */
    @Override
    public Captcha doFillContext(CaptchaContext context) {
        String words = context.getContent();
        Graphics2D graphics = context.getGraphics();
        char[] charArray = words.toCharArray();
        List<String> positions = new ArrayList<>(charArray.length);
        List<String> tooltips = new ArrayList<>(charArray.length);
        // 记录已经生成的x坐标,保证随机数不能一样，即同一位置
        Set<Integer> generatedXPos = new HashSet<>();
        for (Character ch : charArray) {
            FontMetrics fontMetrics = graphics.getFontMetrics();
            int fontWidth = fontMetrics.charWidth(ch);
            int fontHeight = fontMetrics.getHeight();
            int x1 = RandomUtils.random(width - fontWidth, generatedXPos, 30);
            int y1 = RandomUtils.random(fontHeight, height - fontHeight);
            graphics.setColor(randomColor());
            AffineTransform affineTransform = new AffineTransform();
            int centerX = x1 + fontWidth / 2;
            // 字体高度好像不太准确
            int centerY = y1 - fontHeight / 4;
            double radians = Math.toRadians(RandomUtils.random(-45, 45));
            affineTransform.rotate(radians, centerX, centerY);
            graphics.setTransform(affineTransform);
            graphics.drawString(Character.toString(ch), x1, y1);
            positions.add(String.format("%s:%s", centerX, centerY));
            tooltips.add("\"" + ch + "\"");
        }
        graphics.setTransform(new AffineTransform());
        Captcha captcha = new Captcha();
        captcha.setAnswer(positions);
        captcha.setTooltip(StringUtils.collectionToCommaDelimitedString(tooltips));
        return captcha;
    }


    /**
     * 验证码是否有效
     *
     * @param source   原始值
     * @param target   目标值
     * @param accuracy 精度
     * @return boolean true：正确，否则false
     */
    @Override
    public boolean valid(List<String> source, List<String> target, Long accuracy) {
        if (CollectionUtils.isEmpty(target) || source.size() != target.size()) {
            return false;
        }
        for (int i = 0; i < source.size(); i++) {
            if (!validPosition(source.get(i), target.get(i), accuracy)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 默认验证码内容
     *
     * @return String[]
     */
    @Override
    public String getContent() {
        return phraseLibrary.randomOne();
    }

    /**
     * 当前验证码类型
     *
     * @return String
     */
    @Override
    public String getType() {
        return CaptchaEnum.CLICK_TOUCH.getType();
    }

    @Override
    public Font getFont() {
        Font font = fontProvider.get(FontEnum.NUOMITUAN.getName());
        return font.deriveFont(40f);
    }
}
